package com.jsb.laundry.pay;

import com.alibaba.fastjson.JSON;
import com.jsb.laundry.config.properties.WechatMiniPayProperties;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAConfig;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.Base64;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import static com.jsb.laundry.config.properties.WechatMiniPayProperties.*;

/**
 * 原电商支付
 */
@Service("riderPay")
public class JSBPay {
    private static final Logger LOGGER = LoggerFactory.getLogger(JSBPay.class);

    private static Config config;

    @Resource
    private WechatMiniPayProperties wechatMiniPayProperties;
    @PostConstruct
    public void init() {
        config = new RSAConfig.Builder()
                .merchantId(wechatMiniPayProperties.getMerchantId())
                .privateKeyFromPath(privateKeyPath)
                .merchantSerialNumber(wechatMiniPayProperties.getMerchantSerialNumber())
                .wechatPayCertificatesFromPath(wechatPayCertificatePath)
                .build();
    }
    //支付下单
    public String pay(String orderId, String openId, Integer total, String goodsName, String orderIdsStr) {
        LOGGER.info("订单号：" + orderId + "openId:：" + openId + "金额：" + total + "商品昵称：" + goodsName + "回调地址：" + orderIdsStr);
        JsapiService service = new JsapiService.Builder().config(config).build();
        // 调用request.setXxx(val)设置所需参数，具体参数可见Request定义
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(total);
        request.setAmount(amount);
        request.setAppid(wechatMiniPayProperties.getAppId());
        request.setMchid(wechatMiniPayProperties.getMerchantId());
        request.setDescription(goodsName);
//        request.setNotifyUrl(wechatMiniPayProperties.getCallbackUrl());//回调地址
        request.setNotifyUrl(wechatMiniPayProperties.getLaundryCallbackUrl());//回调地址
        request.setOutTradeNo(orderId);
        Payer payer = new Payer();
        payer.setOpenid(openId);
        request.setPayer(payer);
        PrepayResponse response = service.prepay(request);
        String prepayIds = "prepay_id=" + response.getPrepayId();
        LOGGER.info(prepayIds);
        return prepayIds;
    }

    /**
     * 根据聚申宝的支付ID,生成签名从而拉起支付
     *
     * @param prepayId
     * @return
     */
    public  String getToken(String prepayId) {
        String nonceStr = UUID.randomUUID().toString();
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(wechatMiniPayProperties.getAppId(), timestamp, nonceStr, prepayId);
        LOGGER.info("message = " + message);
        String signature = null;
        try {
            signature = sign(message.getBytes("utf-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Object> map = new ConcurrentHashMap<>();
        map.put("appId", wechatMiniPayProperties.getAppId());
        map.put("timestamp", timestamp);
        map.put("nonceStr", nonceStr);
        map.put("prepayId", prepayId);
        map.put("signature", signature);

        return JSON.toJSONString(map);
    }

    static String buildMessage(String appId, long timestamp, String nonceStr, String prepayId) {
        return appId + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + prepayId + "\n";
    }

    /**
     * 根据私钥进行签名Base64解密
     *
     * @param message
     * @return
     * @throws Exception
     */
    public static String sign(byte[] message) throws Exception {
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(getPrivateKey());
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());
    }

    /**
     * 获取私钥对象
     *
     * @return
     * @throws IOException
     */
    private static PrivateKey getPrivateKey() throws IOException {
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
                new FileInputStream(privateKeyPath));
        return merchantPrivateKey;
    }


}
